package com.github.caijh.mall.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.Nonnull;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.github.caijh.commons.util.DateRange;
import com.github.caijh.commons.util.DateUtils;
import com.github.caijh.commons.util.Strings;
import com.github.caijh.mall.constants.Constants;
import com.github.caijh.mall.exception.CrmebException;
import com.github.caijh.mall.utils.vo.DateLimitUtilVo;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.LocalDateTime;

/**
 * Date工具类
 * +----------------------------------------------------------------------
 * | CRMEB [ CRMEB赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 * | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed CRMEB并不是自由软件，未经许可不能去掉CRMEB相关版权
 * +----------------------------------------------------------------------
 * | Author: CRMEB Team <admin@crmeb.com>
 * +----------------------------------------------------------------------
 **/
public final class DateUtil {

    private DateUtil() {
        throw new IllegalStateException("Utility class");
    }


    /**
     * 计算时间范围
     *
     * @param data string 类型
     * @return DateLimitUtilVo
     * @author Mr.Zhang
     * @since 2020-05-06
     * @deprecated use {@code DateUitl.getDateRange}
     */
    @Deprecated
    public static DateLimitUtilVo getDateLimit(String data) {
        //时间计算
        String startTime = null;
        String endTime = DateUtils.nowAsString(Constants.DATE_FORMAT);
        String day = DateUtils.nowAsString(Constants.DATE_FORMAT_START);
        String end = DateUtils.nowAsString(Constants.DATE_FORMAT_END);

        if (!StringUtils.isBlank(data)) {
            switch (data) {
                case Constants.SEARCH_DATE_DAY:
                    startTime = day;
                    break;
                case Constants.SEARCH_DATE_YESTERDAY:
                    startTime = DateUtils.format(LocalDateTime.now().minusDays(1).withMillisOfSecond(0).toDate());
                    endTime = DateUtils.format(LocalDateTime.now().minusDays(1).millisOfDay().withMaximumValue().toDate());
                    break;
                case Constants.SEARCH_DATE_LATELY_7:
                    startTime = DateUtils.format(LocalDateTime.now().minusDays(7).withMillisOfDay(0).toDate());
                    break;
                case Constants.SEARCH_DATE_WEEK:
                    startTime = DateUtils.format(LocalDateTime.now().dayOfWeek().withMinimumValue().withMillisOfDay(0).toDate());
                    endTime = DateUtils.format(LocalDateTime.now().dayOfWeek().withMaximumValue().millisOfDay().withMaximumValue().toDate());
                    break;
                case Constants.SEARCH_DATE_PRE_WEEK:
                    startTime = DateUtils.format(LocalDateTime.now().minusWeeks(1).dayOfWeek().withMinimumValue().withMillisOfDay(0).toDate());
                    endTime = DateUtils.format(LocalDateTime.now().minusWeeks(1).dayOfWeek().withMaximumValue().millisOfDay().withMaximumValue().toDate());
                    break;
                case Constants.SEARCH_DATE_LATELY_30:
                    startTime = DateUtils.format(LocalDateTime.now().minusDays(30).withMillisOfDay(0).toDate());
                    break;
                case Constants.SEARCH_DATE_MONTH:
                    startTime = DateUtils.nowAsString(Constants.DATE_FORMAT_MONTH_START);
                    endTime = DateUtils.format(LocalDateTime.now().dayOfMonth().withMaximumValue().withTime(23, 59, 59, 999).toDate());
                    break;
                case Constants.SEARCH_DATE_PRE_MONTH:
                    startTime = DateUtils.format(LocalDateTime.now().minusMonths(1).dayOfMonth().withMaximumValue().withMillisOfDay(0).toDate());
                    endTime = DateUtils.format(LocalDateTime.now().minusMonths(1).dayOfMonth().withMaximumValue().withTime(23, 59, 59, 999).toDate());
                    break;
                case Constants.SEARCH_DATE_YEAR:
                    startTime = DateUtils.nowAsString(Constants.DATE_FORMAT_YEAR_START);
                    endTime = DateUtils.nowAsString(Constants.DATE_FORMAT_YEAR_END);
                    break;
                case Constants.SEARCH_DATE_PRE_YEAR:
                    startTime = DateUtils.format(LocalDateTime.now().minusYears(1).dayOfYear().withMinimumValue().withMillisOfSecond(0).toDate());
                    endTime = DateUtils.format(LocalDateTime.now().minusYears(1).dayOfYear().withMaximumValue().withTime(23, 59, 59, 999).toDate());
                    break;
                default:
                    List<String> list = Strings.toListByComma(data);
                    if (list.size() == 1) {
                        throw new CrmebException("选择时间参数格式错误，请在 " +
                                Constants.SEARCH_DATE_DAY + "|" +
                                Constants.SEARCH_DATE_YESTERDAY + "|" +
                                Constants.SEARCH_DATE_LATELY_7 + "|" +
                                Constants.SEARCH_DATE_LATELY_30 + "|" +
                                Constants.SEARCH_DATE_MONTH + "|" +
                                Constants.SEARCH_DATE_YEAR + "|自定义时间范围（格式：yyyy-MM-dd HH:mm:ss，两个时间范围用逗号分割）");
                    }
                    startTime = list.get(0);
                    endTime = list.get(1);

                    if (startTime.equals(endTime)) {
                        startTime = DateUtil.appointedDayStrToFormatStr(startTime, Constants.DATE_FORMAT_DATE, Constants.DATE_FORMAT_START);
                        endTime = DateUtil.appointedDayStrToFormatStr(endTime, Constants.DATE_FORMAT_DATE, Constants.DATE_FORMAT_END);
                    }
                    break;
            }
        }
        return new DateLimitUtilVo(startTime, endTime);
    }

    /**
     * 获取某一时间段内的时间集合
     *
     * @param data string 类型
     * @return List<Date>
     * @author Mr.Zhang
     * @since 2020-05-06
     */
    public static List<String> getListDate(String data) {

        //获取30天的开始结束日期
        DateLimitUtilVo dateLimit = DateUtil.getDateLimit(data);

        //定义日期集合
        List<String> date = new ArrayList<>();

        //开始日期
        Date startDate = DateUtils.parse(dateLimit.getStartTime(), Constants.DATE_FORMAT);

        //结束日期
        Date endDate = DateUtils.parse(dateLimit.getEndTime(), Constants.DATE_FORMAT);

        while (endDate.after(startDate)) {
            date.add(DateUtils.format(startDate, Constants.DATE_FORMAT_DATE));
            startDate = DateUtils.addDays(startDate, 1);
        }

        return date;
    }

    /**
     * 获取指定日期指定格式字符串
     *
     * @param dateStr
     * @param DATE_FORMAT
     * @return
     * @throws ParseException
     */
    public static String appointedDayStrToFormatStr(String dateStr, String STR_DATE_FORMAT, String DATE_FORMAT) {
        Date date = DateUtils.parse(dateStr, STR_DATE_FORMAT);
        return DateUtils.format(date, DATE_FORMAT);
    }

    /**
     * 13位时间戳转字符串
     *
     * @param timestamp
     * @param dateFormat
     * @return
     */
    public static String timestamp2DateStr(Long timestamp, String dateFormat) {
        if (ObjectUtil.isNull(timestamp)) {
            return "";
        }
        if (StrUtil.isBlank(dateFormat)) {
            dateFormat = Constants.DATE_FORMAT;
        }
        Date date = new Date(timestamp);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);
        return simpleDateFormat.format(date);
    }

    /**
     * 字符串转13位时间戳
     */
    public static Long dateStr2Timestamp(String dateStr, String type) {
        DateTime parse = cn.hutool.core.date.DateUtil.parse(dateStr);
        if (StrUtil.isNotBlank(type)) {
            if (type.equals(Constants.DATE_TIME_TYPE_BEGIN)) {
                parse = cn.hutool.core.date.DateUtil.beginOfDay(parse);
            }
            if (type.equals(Constants.DATE_TIME_TYPE_END)) {
                parse = cn.hutool.core.date.DateUtil.endOfDay(parse);
            }
        }
        return parse.getTime();
    }

    /**
     * 计算时间范围
     *
     * @param data string 类型
     * @return DateLimitUtilVo
     * @author Mr.Zhang
     * @since 2020-05-06
     */
    @Nonnull
    public static DateRange getDateRange(String data) {
        //时间计算
        Date startTime = null;
        Date endTime = new Date();

        if (!StringUtils.isBlank(data)) {
            switch (data) {
                case Constants.SEARCH_DATE_DAY:
                    startTime = LocalDateTime.now().withMillisOfDay(0).toDate();
                    break;
                case Constants.SEARCH_DATE_YESTERDAY:
                    startTime = LocalDateTime.now().minusDays(1).withMillisOfDay(0).toDate();
                    endTime = LocalDateTime.fromDateFields(startTime).hourOfDay().withMaximumValue().toDate();
                    break;
                case Constants.SEARCH_DATE_LATELY_7:
                    startTime = LocalDateTime.now().minusDays(-7).withMillisOfDay(0).toDate();
                    break;
                case Constants.SEARCH_DATE_WEEK:
                    startTime = LocalDateTime.now().dayOfWeek().withMinimumValue().toDate();
                    endTime = LocalDateTime.now().dayOfWeek().withMaximumValue().toDate();
                    break;
                case Constants.SEARCH_DATE_PRE_WEEK:
                    startTime = LocalDateTime.now().minusWeeks(1).withMillisOfDay(0).toDate();
                    endTime = LocalDateTime.fromDateFields(startTime).dayOfWeek().withMinimumValue().toDate();
                    break;
                case Constants.SEARCH_DATE_LATELY_30:
                    startTime = LocalDateTime.now().withMillisOfDay(0).minusDays(30).toDate();
                    break;
                case Constants.SEARCH_DATE_MONTH:
                    startTime = LocalDateTime.now().withDayOfMonth(1).withMillisOfDay(0).toDate();
                    endTime = LocalDateTime.fromDateFields(startTime).dayOfMonth().withMaximumValue().toDate();
                    break;
                case Constants.SEARCH_DATE_PRE_MONTH:
                    startTime = LocalDateTime.now().minusMonths(1).dayOfMonth().withMinimumValue().toDate();
                    endTime = LocalDateTime.fromDateFields(startTime).dayOfMonth().withMaximumValue().toDate();
                    break;
                case Constants.SEARCH_DATE_YEAR:
                    startTime = LocalDateTime.now().dayOfYear().withMinimumValue().toDate();
                    endTime = LocalDateTime.now().dayOfYear().withMaximumValue().toDate();
                    break;
                case Constants.SEARCH_DATE_PRE_YEAR:
                    startTime = LocalDateTime.now().minusYears(1).dayOfYear().withMinimumValue().toDate();
                    endTime = LocalDateTime.fromDateFields(startTime).dayOfYear().withMaximumValue().toDate();
                    break;
                default:
                    List<String> list = Strings.toListByComma(data);
                    if (list.size() == 1) {
                        throw new CrmebException("选择时间参数格式错误，请在 " +
                                Constants.SEARCH_DATE_DAY + "|" +
                                Constants.SEARCH_DATE_YESTERDAY + "|" +
                                Constants.SEARCH_DATE_LATELY_7 + "|" +
                                Constants.SEARCH_DATE_LATELY_30 + "|" +
                                Constants.SEARCH_DATE_MONTH + "|" +
                                Constants.SEARCH_DATE_YEAR + "|自定义时间范围（格式：yyyy-MM-dd HH:mm:ss，两个时间范围用逗号分割）");
                    }
                    startTime = DateUtils.parse(list.get(0));
                    endTime = DateUtils.parse(list.get(1));
                    break;
            }
        }
        return new DateRange(startTime, endTime);
    }

}
